"""ReAct 流式服务 - 实现真正的思考过程流式输出"""

import asyncio
import json
import logging
import time
import uuid
from typing import Dict, List, Any, Optional, AsyncGenerator
from sqlalchemy.orm import Session
from sqlalchemy import text

logger = logging.getLogger(__name__)


class ReactStreamingService:
    """ReAct 流式服务 - 支持思考过程的实时流式输出和存储"""

    def __init__(self, db: Session = None):
        """初始化流式服务"""
        from app.core.react import react_controller
        self.react_controller = react_controller
        self.db = db
        # 存储思考过程的变量
        self.thinking_content = ""
        self.thinking_iterations = []
        self.current_iteration = 1
        logger.info(f"[ReactStreaming] ReAct控制器初始化成功: {type(self.react_controller)}")
        
    async def stream_react_process(
        self,
        user_input: str,
        chat_history: List[Dict] = None,
        conversation_id: str = None,
        user_id: str = None
    ) -> AsyncGenerator[str, None]:
        """
        流式 ReAct 处理 - 实时返回思考过程和最终答案

        Args:
            user_input: 用户输入
            chat_history: 对话历史
            conversation_id: 对话ID
            user_id: 用户ID

        Yields:
            JSON 格式的流式数据
        """
        # 添加详细的参数调试日志 - 使用print确保输出
        print(f"[ReactStreaming] ===== stream_react_process 开始 =====")
        print(f"[ReactStreaming] 接收到的参数:")
        print(f"[ReactStreaming] - user_input: {user_input[:50]}...")
        print(f"[ReactStreaming] - chat_history: {len(chat_history) if chat_history else 0} 条消息")
        print(f"[ReactStreaming] - conversation_id: {conversation_id}")
        print(f"[ReactStreaming] - user_id: {user_id}")
        print(f"[ReactStreaming] - self.db: {self.db is not None}")

        logger.info(f"[ReactStreaming] ===== stream_react_process 开始 =====")
        logger.info(f"[ReactStreaming] 接收到的参数:")
        logger.info(f"[ReactStreaming] - user_input: {user_input[:50]}...")
        logger.info(f"[ReactStreaming] - chat_history: {len(chat_history) if chat_history else 0} 条消息")
        logger.info(f"[ReactStreaming] - conversation_id: {conversation_id}")
        logger.info(f"[ReactStreaming] - user_id: {user_id}")
        logger.info(f"[ReactStreaming] - self.db: {self.db is not None}")

        # 检查数据库连接状态
        print(f"[ReactStreaming] 🔍 开始数据库连接测试...")
        if self.db is not None:
            try:
                # 测试数据库连接
                print(f"[ReactStreaming] 🔍 执行数据库测试查询...")
                self.db.execute(text("SELECT 1"))
                print(f"[ReactStreaming] ✅ 数据库连接测试成功")
                logger.info(f"[ReactStreaming] 数据库连接测试成功")
            except Exception as db_test_error:
                print(f"[ReactStreaming] ❌ 数据库连接测试失败: {db_test_error}")
                logger.error(f"[ReactStreaming] 数据库连接测试失败: {db_test_error}")
        else:
            print(f"[ReactStreaming] ⚠️ 数据库连接为None！")
            logger.warning(f"[ReactStreaming] 数据库连接为None！")

        print(f"[ReactStreaming] 🔍 数据库测试完成，继续处理...")

        # 发送开始信号
        print(f"[ReactStreaming] 🔍 准备发送开始信号...")
        try:
            yield self._format_stream_data({
                "type": "start",
                "message": "🧠 AI开始思考...",
                "timestamp": time.time()
            })
            print(f"[ReactStreaming] ✅ 开始信号发送成功")
        except Exception as e:
            print(f"[ReactStreaming] ❌ 发送开始信号失败: {e}")
            raise

        # 发送用户消息
        print(f"[ReactStreaming] 🔍 准备发送用户消息...")
        try:
            yield self._format_stream_data({
                "type": "user_message",
                "content": user_input,
                "timestamp": time.time()
            })
            print(f"[ReactStreaming] ✅ 用户消息发送成功")
        except Exception as e:
            print(f"[ReactStreaming] ❌ 发送用户消息失败: {e}")
            raise

        # 创建或获取对话ID
        print(f"[ReactStreaming] 🔍 检查是否需要创建新对话:")
        print(f"[ReactStreaming] - conversation_id存在: {conversation_id is not None}")
        print(f"[ReactStreaming] - self.db存在: {self.db is not None}")
        print(f"[ReactStreaming] - user_id存在: {user_id is not None}")

        logger.info(f"[ReactStreaming] 检查是否需要创建新对话:")
        logger.info(f"[ReactStreaming] - conversation_id存在: {conversation_id is not None}")
        logger.info(f"[ReactStreaming] - self.db存在: {self.db is not None}")
        logger.info(f"[ReactStreaming] - user_id存在: {user_id is not None}")

        if not conversation_id and self.db and user_id:
            print(f"[ReactStreaming] ✅ 满足创建新对话的条件，开始创建...")
            logger.info(f"[ReactStreaming] 满足创建新对话的条件，开始创建...")
            try:
                conversation_id = await self._create_conversation(user_id, user_input)
                print(f"[ReactStreaming] ✅ 创建新对话成功: {conversation_id}")
                logger.info(f"[ReactStreaming] 创建新对话成功: {conversation_id}")
            except Exception as e:
                print(f"[ReactStreaming] ❌ 创建新对话失败: {e}")
                logger.error(f"[ReactStreaming] 创建新对话失败: {e}")
                raise
        else:
            print(f"[ReactStreaming] ⚠️ 不满足创建新对话的条件，跳过创建")
            logger.info(f"[ReactStreaming] 不满足创建新对话的条件，跳过创建")

        # 保存用户消息到数据库
        logger.info(f"[ReactStreaming] 检查是否需要保存用户消息:")
        logger.info(f"[ReactStreaming] - self.db存在: {self.db is not None}")
        logger.info(f"[ReactStreaming] - conversation_id存在: {conversation_id is not None}")
        logger.info(f"[ReactStreaming] - user_id存在: {user_id is not None}")

        if self.db and conversation_id and user_id:
            logger.info(f"[ReactStreaming] 满足保存用户消息的条件，开始保存...")
            await self._save_user_message(conversation_id, user_input)
            logger.info(f"[ReactStreaming] 保存用户消息成功")
        else:
            logger.warning(f"[ReactStreaming] 不满足保存用户消息的条件，跳过保存")

        # 发送 ReAct 开始信号
        yield self._format_stream_data({
            "type": "react_start",
            "message": "🔄 启动ReAct推理架构...",
            "timestamp": time.time()
        })

        # 重置思考过程存储
        self.thinking_content = ""
        self.thinking_iterations = []
        self.current_iteration = 1

        # 使用真实的 ReAct 控制器
        ai_response = ""
        async for data_str in self._stream_real_react(user_input, chat_history, conversation_id):
            # 解析流式数据
            try:
                # 提取JSON数据
                if data_str.startswith("data: "):
                    json_str = data_str[6:].strip()
                    if json_str:
                        data = json.loads(json_str)
                        # 收集AI响应内容
                        if data.get("type") == "content":
                            ai_response += data.get("content", "")
                        # 收集思考过程内容
                        elif data.get("type") == "thinking_chunk":
                            logger.info(f"[ReactStreaming] 收到思考片段: {data.get('content', '')[:50]}...")
                            await self._collect_thinking_content(data)
            except:
                pass
            yield data_str

        # 保存AI响应和思考过程到数据库
        logger.info(f"[ReactStreaming] ===== 准备保存AI消息 =====")
        logger.info(f"[ReactStreaming] 保存前状态检查:")
        logger.info(f"[ReactStreaming] - AI响应长度: {len(ai_response)}")
        logger.info(f"[ReactStreaming] - 思考内容长度: {len(self.thinking_content)}")
        logger.info(f"[ReactStreaming] - 思考迭代数: {len(self.thinking_iterations)}")
        logger.info(f"[ReactStreaming] - self.db存在: {self.db is not None}")
        logger.info(f"[ReactStreaming] - conversation_id: {conversation_id}")
        logger.info(f"[ReactStreaming] - user_id: {user_id}")

        # 保存AI响应到数据库（如果有数据库连接）
        saved_message_id = None
        if self.db and conversation_id and user_id:
            logger.info(f"[ReactStreaming] 满足保存条件，开始保存AI消息...")
            # 如果有AI响应内容，保存完整的消息和思考过程
            if ai_response:
                logger.info(f"[ReactStreaming] 有AI响应内容，保存完整消息和思考过程")
                saved_message_id = await self._save_ai_message_with_thinking(conversation_id, ai_response, user_id)
                logger.info(f"[ReactStreaming] 完整消息和思考过程保存成功，消息ID: {saved_message_id}")
            # 如果没有AI响应但有思考过程，也要保存思考过程
            elif self.thinking_content or self.thinking_iterations:
                logger.info(f"[ReactStreaming] 没有AI响应内容，但有思考过程，仍然保存")
                saved_message_id = await self._save_ai_message_with_thinking(conversation_id, "思考过程记录", user_id)
                logger.info(f"[ReactStreaming] 思考过程记录保存成功，消息ID: {saved_message_id}")
            else:
                logger.warning(f"[ReactStreaming] 没有AI响应内容，也没有思考过程，跳过保存")
        else:
            logger.error(f"[ReactStreaming] ❌ 保存条件不满足！详细信息:")
            logger.error(f"[ReactStreaming] - db存在: {self.db is not None}")
            logger.error(f"[ReactStreaming] - conversation_id存在: {conversation_id is not None}")
            logger.error(f"[ReactStreaming] - conversation_id值: {conversation_id}")
            logger.error(f"[ReactStreaming] - user_id存在: {user_id is not None}")
            logger.error(f"[ReactStreaming] - user_id值: {user_id}")

            # 如果数据库连接存在但其他参数为空，这可能是参数传递问题
            if self.db is not None:
                logger.error(f"[ReactStreaming] 数据库连接正常，但参数传递有问题！")
                logger.error(f"[ReactStreaming] 这可能是前端调用或API参数传递的问题")
            else:
                logger.error(f"[ReactStreaming] 数据库连接为None，这是数据库连接问题！")

        # 发送完成信号（包含conversation_id和message_id）
        yield self._format_stream_data({
            "type": "complete",
            "message": "✅ ReAct处理完成",
            "conversation_id": conversation_id,
            "message_id": saved_message_id,  # 添加保存的消息ID
            "timestamp": time.time()
        })

    async def _stream_real_react(
        self,
        user_input: str,
        chat_history: List[Dict],
        conversation_id: str
    ) -> AsyncGenerator[str, None]:
        """使用真实的 ReAct 控制器进行流式处理"""
        logger.info(f"[ReactStreaming] 开始真实ReAct处理: {user_input[:50]}...")

        # 创建流式数据队列
        stream_queue = asyncio.Queue()

        # 创建流式回调函数
        async def stream_callback(data):
            """实时流式回调 - 立即放入队列"""
            logger.info(f"[ReactStreaming] 收到回调数据: {data.get('type', 'unknown')} - {str(data)[:100]}...")
            await stream_queue.put(data)
            logger.debug(f"[ReactStreaming] 数据已放入队列，当前队列大小: {stream_queue.qsize()}")

        # 定义 ReAct 处理任务
        async def run_react():
            logger.info(f"[ReactStreaming] 调用ReAct控制器...")
            logger.info(f"[ReactStreaming] 用户输入: {user_input}")
            logger.info(f"[ReactStreaming] 历史消息数量: {len(chat_history or [])}")
            logger.info(f"[ReactStreaming] 回调函数: {stream_callback}")

            result = await self.react_controller.process_message(
                user_input=user_input,
                chat_history=chat_history or [],
                stream_callback=stream_callback
            )
            logger.info(f"[ReactStreaming] ReAct处理完成")
            logger.info(f"[ReactStreaming] 结果类型: {type(result)}")
            logger.info(f"[ReactStreaming] 结果内容: {result}")

            # 处理完成后发送最终答案
            if result and result.get("response"):
                logger.info(f"[ReactStreaming] 发送最终答案: {result['response'][:50]}...")
                # 分块发送最终答案
                final_answer = result["response"]
                chunk_size = 30
                for i in range(0, len(final_answer), chunk_size):
                    chunk = final_answer[i:i + chunk_size]
                    await stream_callback({
                        "type": "content",
                        "content": chunk
                    })
                    await asyncio.sleep(0.05)  # 模拟打字效果
            else:
                logger.warning(f"[ReactStreaming] 没有收到响应内容")
                await stream_callback({
                    "type": "content",
                    "content": "抱歉，我在处理您的问题时遇到了困难。"
                })

            logger.info(f"[ReactStreaming] run_react 任务完成")

        # 启动 ReAct 任务
        logger.info(f"[ReactStreaming] 启动ReAct任务...")
        react_task = asyncio.create_task(run_react())
        logger.info(f"[ReactStreaming] ReAct任务已创建: {react_task}")

        # 处理流式数据
        loop_count = 0
        while True:
            loop_count += 1
            logger.debug(f"[ReactStreaming] 流式处理循环 #{loop_count}")

            # 等待数据或任务完成
            queue_task = asyncio.create_task(stream_queue.get())
            logger.debug(f"[ReactStreaming] 等待数据或任务完成...")

            done, pending = await asyncio.wait(
                [queue_task, react_task],
                return_when=asyncio.FIRST_COMPLETED,
                timeout=2.0
            )

            logger.debug(f"[ReactStreaming] 等待结果: done={len(done)}, pending={len(pending)}")

            if done:
                react_task_completed = False
                for task in done:
                    if task == react_task:
                        # ReAct 任务完成
                        logger.info(f"[ReactStreaming] ReAct任务完成")
                        react_task_completed = True
                    elif task == queue_task:
                        # 收到流式数据
                        data = task.result()
                        logger.info(f"[ReactStreaming] 收到流式数据: {data.get('type', 'unknown')} - {str(data)[:100]}...")
                        yield self._format_stream_data({
                            **data,
                            "timestamp": time.time()
                        })

                # 如果 ReAct 任务完成，标记退出但不立即 break
                if react_task_completed:
                    logger.info(f"[ReactStreaming] ReAct任务已完成，准备退出循环")

            # 只取消队列任务，不要取消 ReAct 任务
            for task in pending:
                if task != react_task:
                    logger.debug(f"[ReactStreaming] 取消队列任务: {task}")
                    task.cancel()
                else:
                    logger.debug(f"[ReactStreaming] 保留ReAct任务: {task}")

            # 检查任务是否完成
            if react_task.done():
                logger.info(f"[ReactStreaming] 检测到任务完成，退出循环")
                break

            # 防止无限循环
            if loop_count > 1000:
                logger.warning(f"[ReactStreaming] 循环次数过多，强制退出")
                break

        # 处理剩余的队列数据
        logger.info(f"[ReactStreaming] 处理剩余队列数据...")
        remaining_count = 0
        while not stream_queue.empty():
            remaining_count += 1
            data = stream_queue.get_nowait()
            logger.info(f"[ReactStreaming] 剩余数据 #{remaining_count}: {data.get('type', 'unknown')}")
            yield self._format_stream_data({
                **data,
                "timestamp": time.time()
            })

        logger.info(f"[ReactStreaming] 流式处理完成，总循环次数: {loop_count}, 剩余数据: {remaining_count}")



    def _format_stream_data(self, data: Dict[str, Any]) -> str:
        """
        格式化流式数据

        Args:
            data: 要格式化的数据

        Returns:
            格式化后的 JSON 字符串
        """
        return f"data: {json.dumps(data, ensure_ascii=False)}\n\n"

    async def _create_conversation(self, user_id: str, first_message: str) -> str:
        """创建新对话"""
        from app.models import Conversation
        from app.utils.datetime_utils import beijing_now_naive

        conversation_id = f"user_{user_id}_{int(time.time())}"

        # 生成对话标题（取前20个字符）
        title = first_message[:20] + "..." if len(first_message) > 20 else first_message

        conversation = Conversation(
            conversation_id=conversation_id,
            user_id=user_id,
            title=title,
            created_at=beijing_now_naive(),
            updated_at=beijing_now_naive()
        )

        self.db.add(conversation)
        self.db.commit()
        self.db.refresh(conversation)

        logger.info(f"[ReactStreaming] 创建对话成功: {conversation_id}")
        return conversation_id

    async def _save_user_message(self, conversation_id: str, content: str):
        """保存用户消息"""
        from app.models import Message
        from app.utils.datetime_utils import beijing_now_naive

        message_id = f"msg_{int(time.time())}_{uuid.uuid4().hex[:8]}"

        message = Message(
            message_id=message_id,
            conversation_id=conversation_id,
            role="user",
            content=content,
            created_at=beijing_now_naive()
        )

        self.db.add(message)
        self.db.commit()
        logger.info(f"[ReactStreaming] 保存用户消息: {message_id}")

    async def _collect_thinking_content(self, data: Dict[str, Any]):
        """收集思考过程内容"""
        try:
            # 检测新的迭代
            iteration = data.get("iteration", 1)
            if iteration != self.current_iteration:
                # 保存上一个迭代的内容
                if self.thinking_content:
                    self.thinking_iterations.append({
                        "iteration": self.current_iteration,
                        "content": self.thinking_content,
                        "timestamp": time.time()
                    })

                # 开始新的迭代
                self.current_iteration = iteration
                self.thinking_content = ""

            # 累积思考内容
            if data.get("full_content_so_far"):
                self.thinking_content = data["full_content_so_far"]
            elif data.get("content"):
                self.thinking_content += data["content"]

            logger.debug(f"[ReactStreaming] 收集思考内容: 迭代{iteration}, 长度{len(self.thinking_content)}")
        except Exception as e:
            logger.error(f"[ReactStreaming] 收集思考内容失败: {e}")

    async def _save_ai_message_with_thinking(self, conversation_id: str, content: str, user_id: str) -> str:
        """保存AI响应消息和思考过程，返回消息ID"""
        from app.models import Message
        from app.utils.datetime_utils import beijing_now_naive
        import json

        message_id = f"msg_{int(time.time())}_{uuid.uuid4().hex[:8]}"

        # 保存当前迭代的思考内容
        if self.thinking_content:
            self.thinking_iterations.append({
                "iteration": self.current_iteration,
                "content": self.thinking_content,
                "timestamp": time.time()
            })

        # 构建思考过程元数据
        thinking_metadata = {
            "thinking_process": {
                "iterations": self.thinking_iterations,
                "total_iterations": len(self.thinking_iterations),
                "total_thinking_content": "\n\n".join([
                    f"=== 第{iter_data['iteration']}次思考 ===\n{iter_data['content']}"
                    for iter_data in self.thinking_iterations
                ]),
                "created_at": time.time()
            }
        }

        message = Message(
            message_id=message_id,
            conversation_id=conversation_id,
            role="assistant",
            content=content,
            created_at=beijing_now_naive()
        )

        # 使用模型的set_metadata方法设置思考过程元数据
        message.set_metadata(thinking_metadata)

        self.db.add(message)
        self.db.commit()
        logger.info(f"[ReactStreaming] 保存AI消息: {message_id}")

        # 同时保存思考过程到chromaDB
        await self._save_thinking_to_chroma(message_id, user_id, thinking_metadata)

        # 返回消息ID
        return message_id

    async def _save_thinking_to_chroma(self, message_id: str, user_id: str, thinking_metadata: Dict[str, Any]):
        """将思考过程保存到chromaDB"""
        try:
            from app.core.vector_store import get_vector_store

            vector_store = get_vector_store()
            if not vector_store:
                logger.warning("[ReactStreaming] ChromaDB不可用，跳过思考过程存储")
                return

            thinking_process = thinking_metadata.get("thinking_process", {})
            total_thinking_content = thinking_process.get("total_thinking_content", "")

            if not total_thinking_content:
                logger.info("[ReactStreaming] 没有思考内容，跳过ChromaDB存储")
                return

            # 构建ChromaDB文档
            document_id = f"thinking_{message_id}"
            metadata = {
                "type": "thinking_process",
                "message_id": message_id,
                "user_id": user_id,
                "total_iterations": thinking_process.get("total_iterations", 0),
                "created_at": thinking_process.get("created_at", time.time()),
                "content_length": len(total_thinking_content)
            }

            # 添加到向量数据库
            vector_store.add_texts(
                texts=[total_thinking_content],
                metadatas=[metadata],
                ids=[document_id]
            )

            logger.info(f"[ReactStreaming] 思考过程已保存到ChromaDB: {document_id}")

        except Exception as e:
            logger.error(f"[ReactStreaming] 保存思考过程到ChromaDB失败: {e}")

    async def get_thinking_by_message_id(self, message_id: str) -> Optional[Dict[str, Any]]:
        """通过message_id获取思考过程"""
        try:
            from app.models import Message

            # 从MySQL获取消息
            message = self.db.query(Message).filter(Message.message_id == message_id).first()
            if not message:
                return None

            # 使用模型的get_metadata方法获取元数据
            metadata = message.get_metadata()
            thinking_process = metadata.get("thinking_process")

            if thinking_process:
                logger.info(f"[ReactStreaming] 获取思考过程: {message_id}")
                return thinking_process

            return None

        except Exception as e:
            logger.error(f"[ReactStreaming] 获取思考过程失败: {e}")
            return None


# 创建全局实例
react_streaming_service = ReactStreamingService()
